/**
 * <code>UserPhoneHandler.java</code>	2013-09-10
 * 
 * Copyright (c) 2008-2013  自动生成的 all rights reserved.
 */
package com.jf.cloud.service.sysmanager.dao.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.service.spi.ServiceException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.jf.cloud.service.sysmanager.common.base.BaseService;
import com.jf.cloud.service.sysmanager.common.db.BaseDao;
import com.jf.cloud.service.sysmanager.common.db.jdbc.RowMapperFactory;
import com.jf.cloud.service.sysmanager.common.util.DateUtil;
import com.jf.cloud.service.sysmanager.common.util.RandomUtil;
import com.jf.cloud.service.sysmanager.common.util.RegexValidUtil;
import com.jf.cloud.service.sysmanager.common.util.StringUtil;
import com.jf.cloud.service.sysmanager.constant.sms.SmsConstant;
import com.jf.cloud.service.sysmanager.constant.sms.SmsResult;
import com.jf.cloud.service.sysmanager.dao.ISmsService;
import com.jf.cloud.service.sysmanager.entity.PubgPhoneMsg;
import com.jf.cloud.service.sysmanager.entity.sms.BaseSmsApiConfig;
import com.jf.cloud.service.sysmanager.entity.sms.SmsMessage;
import com.jf.cloud.service.sysmanager.handler.GaniuSmsHandler;
import com.jf.cloud.service.sysmanager.handler.PropConfigHandler;
import com.jf.cloud.service.sysmanager.support.entity.Result;

/**
 * 手机验证码 发送、校验相关处理器 
 * 
 * @author 程伟平 创建时间：2013-09-10 11:22:33
 */
@Service("smsService")
public class SmsServiceImpl extends BaseService<PubgPhoneMsg, Long> implements ISmsService {

	/**
	 * 日志
	 */
	private static Log log = LogFactory.getLog(SmsServiceImpl.class);
	
	/**
	 * JPA公共DAO
	 */
	@Resource
	private BaseDao baseDao;
	
	/**
	 * 
	 * 发送短信
	 * 
	 * @author 姚龙   创建时间：2017-05-02 17:06:54
	 */
	public SmsResult sendSMS(String userPhone, String smsContent) {
		SmsResult smsResult = new SmsResult();
		smsResult.setCode("-1");
		try {
			if (StringUtil.isNull(userPhone)) {
				smsResult.setInfo("手机号为空！");
				return smsResult;
			}
			if (!RegexValidUtil.compile(RegexValidUtil.mobile, userPhone)) {
				smsResult.setInfo("手机号格式错误！");
				return smsResult;
			}
			if (StringUtil.isNull(smsContent)) {
				smsResult.setInfo("短信内容为空！");
				return smsResult;
			}
			
			// 当前开启的短信接口配置信息
			BaseSmsApiConfig config = SmsConstant.config;
			if (config == null) { // 不考虑并发重复查询问题,等用户量大时再考虑
				config = this.findOpenedSmsApiConfig();
				if (config != null) {
					SmsConstant.config = config; // 短信接口配置切换时会置为空
				}
			}
			if (config == null) {
				smsResult.setInfo("短信接口配置信息为空或未开启");
				return smsResult;
			}
			if (StringUtil.isNull(config.getSmsAccount())) {
				smsResult.setInfo("短信账号为空！");
				return smsResult;
			}
			if (StringUtil.isNull(config.getSmsSendUrl())) {
				smsResult.setInfo("短信发送地址为空！");
				return smsResult;
			}
		
			// 开始发送短信
			if (SmsConstant.SMS_PLATFORM_TYPE_3.equals(config.getSmsQdId().toString())) { // 嘎牛
				if (StringUtil.isNull(config.getSmsAccountKey())) {
					smsResult.setInfo("嘎牛短信Key为空！");
					return smsResult;
				}
				if (StringUtil.isNull(config.getSmsAccountPwd())) {
					smsResult.setInfo("嘎牛短信密码为空！");
					return smsResult;
				}
				SmsMessage message = new SmsMessage();
				message.setPhoneNos(userPhone);
				message.setMessageContent(smsContent);
				smsResult = GaniuSmsHandler.sendSMS(message, config);
			}
		} catch (Exception e) {
			log.error("发送短信出错", e);
			smsResult.setInfo("发送短信出错了");
		}
		return smsResult;
	}

	/**
	 * 根据用户ID、用户手机、模块类型查询手机验证码
	 * 
	 * @author 程伟平 创建时间：2013-09-10
	 */
	public PubgPhoneMsg findUserPhoneYzm(Long userId, String userPhone, String modelType) {
		PubgPhoneMsg userPhoneYzm = null;
		String sql = "";
		try {
			if (userId == null) {
				sql = " SELECT * FROM pubg_phone_msg WHERE USER_PHONE = ? AND MODEL_TYPE = ? AND PHONE_YZM_STATE = '1' ORDER BY PHONE_YZM_CF_TIME DESC LIMIT 1";
				userPhoneYzm = this.baseDao.findObject(sql, RowMapperFactory.newInstance(PubgPhoneMsg.class), userPhone, modelType);
			} else {
				sql = " SELECT * FROM pubg_phone_msg WHERE USER_ID = ? AND USER_PHONE = ? AND MODEL_TYPE = ? AND PHONE_YZM_STATE = '1' ORDER BY PHONE_YZM_CF_TIME DESC LIMIT 1";
				userPhoneYzm = this.baseDao.findObject(sql, RowMapperFactory.newInstance(PubgPhoneMsg.class), userId, userPhone, modelType);
			}
		} catch (Exception e) {
			log.error("根据用户ID、用户手机、模块类型查询手机验证码出错了！", e);
		}
		return userPhoneYzm;
	}

	/**
	 * 根据模块类型获取模块类型名称
	 * 
	 * @author 程伟平 创建时间：2013-09-10 14:30:20
	 */
	private String getModelTypeName(String modelType) {
		String modelTypeName = "";
		if (SmsConstant.USER_PHONE_MODEL_TYPE_100.equals(modelType)) {
			modelTypeName = "申请账号注册验证";
		} else if (SmsConstant.USER_PHONE_MODEL_TYPE_110.equals(modelType)) {
			modelTypeName = "申请找回密码验证";
		}
		return modelTypeName;
	}

	/**
	 * 根据验证功能和短信验证码构建短信内容
	 * 
	 * @author 程伟平 创建时间：2013-09-18 14:46:29
	 */
	private String buildSMSContent(String smsModelName, String smsCode) {
		String dlSign = PropConfigHandler.getBasePropConfig(SmsConstant.SMS_SIGN_KEY);
		if (StringUtil.isNull(dlSign)) {
			dlSign = "【吃鸡竞技】";
		}
		return dlSign + "验证码：" + smsCode + "，您正在" + smsModelName + "，如有问题请联系客服。";
	}

	/**
	 * 
	 * 发送验证码短信
	 * 
	 * @author 姚龙   创建时间：2017-05-02 16:44:02
	 */
	@Transactional
	public String sendCaptchaSms(String userPhone, String modelType) throws ServiceException {
		SmsResult smsResult = null;
		try {
			PubgPhoneMsg userPhoneYzm = findUserPhoneYzm(null, userPhone, modelType);
			if (userPhoneYzm != null) {
				if (Calendar.getInstance().getTime().before(DateUtil.parse(userPhoneYzm.getPhoneYzmCfTime()))) {
					return "-10000:尚未到达重新发送时间，请您稍后再试！";
				}
			} else {
				userPhoneYzm = new PubgPhoneMsg();
				userPhoneYzm.setUserPhone(userPhone); 
				userPhoneYzm.setModelType(modelType);
			}
			userPhoneYzm.setPhoneYzm(RandomUtil.getRandomNumber(SmsConstant.USER_PHONE_YZM_SIZE));
			userPhoneYzm.setPhoneYzmLimit(DateUtil.getDateTime(Calendar.MINUTE, SmsConstant.USER_PHONE_YZM_LIMIT));
			userPhoneYzm.setPhoneYzmState(SmsConstant.USER_PHONE_YZM_STATE_1);
			userPhoneYzm.setPhoneYzmCfTime(DateUtil.getDateTime(Calendar.MINUTE, SmsConstant.USER_PHONE_YZM_CF_LIMIT));
			userPhoneYzm.setLastModifyTime(DateUtil.getCurrentDateTime());
			
			// 发送短信
			String smsContent = buildSMSContent(getModelTypeName(modelType), userPhoneYzm.getPhoneYzm());
			smsResult = this.sendSMS(userPhone, smsContent);
			/*smsResult = new SmsResult();
			smsResult.setCode("0");*/
			if (smsResult != null) {
				this.baseDao.saveAll(userPhoneYzm);
			} else {
				smsResult = new SmsResult();
				smsResult.setCode("-1");
				smsResult.setInfo("短信发送结果为空");
			}
			
		} catch (Exception e) {
			throw new ServiceException("发送验证码短信出错了", e);
		}
		return "-1".equals(smsResult.getCode()) ? smsResult.getCode() + "-" + smsResult.getInfo() : smsResult.getCode();
	}

	/**
	 * 
	 * 验证 手机验证码 0:成功 其他为错误代码+原因描述
	 * 
	 * @author 姚龙   创建时间：2017-05-06 14:38:51
	 */
	public String checkSMS(Long userId, String userPhone, String modelType, String phoneCode) throws Exception {
		PubgPhoneMsg userPhoneYzm = findUserPhoneYzm(userId, userPhone, modelType);
		if (userPhoneYzm == null || phoneCode == null || !phoneCode.equals(userPhoneYzm.getPhoneYzm())) {
			return "验证码不正确";
		}
		if (SmsConstant.USER_PHONE_YZM_STATE_0.equals(userPhoneYzm.getPhoneYzmState())) {
			return "验证码不可用";
		}
		Date dateTime = Calendar.getInstance().getTime();
		Date limitTime = DateUtil.parse(userPhoneYzm.getPhoneYzmLimit());
		if (dateTime.getTime() >= limitTime.getTime()) {
			return "验证码已过期";
		}
		return "0";
	}

	/**
	 * 更新手机验证码状态为0不可用
	 * 
	 * @author 程伟平 创建时间：2013-09-10 15:30:20
	 */
	@Transactional
	public void updateUserPhoneYzmState(Long userId, String userPhone, String modelType) throws ServiceException {
		String sql = "";
		try {
			if (userId != null) {
				sql = " UPDATE pubg_phone_msg SET PHONE_YZM_STATE = '0' WHERE USER_ID = ? AND USER_PHONE = ? AND MODEL_TYPE = ? ";
				this.baseDao.safeUpdate(sql, 0, userId, userPhone, modelType);
			} else {
				sql = " UPDATE pubg_phone_msg SET PHONE_YZM_STATE = '0' WHERE USER_PHONE = ? AND MODEL_TYPE = ? ";
				this.baseDao.safeUpdate(sql, 0, userPhone, modelType);
			}
		} catch (Exception e) {
			throw new ServiceException("更新手机验证码状态为0不可用时出错了", e);
		}
	}

	/**
	 * 
	 * 检查是否可以发送短信
	 * 
	 * @author 姚龙   创建时间：2017-05-02 14:26:50
	 */
	public Result<String> check(String ip, String phoneNo, String modelType) {
		Result<String> result = new Result<String>();
		result.setCode(-1);
		result.setMessage("检查状态失败");
		try {
			if (StringUtil.isNull(phoneNo)) {
				result.setMessage("手机号为空");
				return result;
			}
			if (!RegexValidUtil.compile(RegexValidUtil.mobile, phoneNo)) {
				result.setMessage("手机号格式错误！");
				return result;
			}
			if (StringUtil.isEmpty(modelType)) {
				result.setMessage("短信类型为空！");
				return result;
			}
			
			log.info(" 1个号码 一分钟 多少次");
			String sql = " SELECT COUNT(1) FROM pubg_phone_msg a WHERE a.USER_PHONE = ? AND MODEL_TYPE = ? AND a.PHONE_YZM_CF_TIME >= DATE_ADD(NOW(), INTERVAL -1 MINUTE) ";
			int count = baseDao.find(sql, Integer.class, phoneNo, modelType);
			if (count >= 1) {
				result.setCode(-101);
				result.setMessage("已超过一分钟发送上限，请您稍后再试 ！");
				return result;
			}
			
			log.info(" 1个号码 24小时 多少次");
			sql = " SELECT COUNT(1) FROM pubg_phone_msg a WHERE a.USER_PHONE = ? AND MODEL_TYPE = ? AND a.PHONE_YZM_CF_TIME >= DATE_ADD(NOW(), INTERVAL -24 HOUR) ";
			count = baseDao.find(sql, Integer.class, phoneNo, modelType);
			if (count >= 20) {
				result.setCode(-102);
				result.setMessage("已超过当天发送上限，请联系管理员！");
				return result;
			}
			result.setCode(0);
		} catch (Exception e) {
			log.error("用户手机次数验证 失败", e);
		}
		return result;
	}
	
	/**
	 * 根据模块类型判断手机验证码是否存在
	 * 
	 * @author 程伟平 创建时间：2013-09-10 13:30:37
	 */
	public boolean isExist(String userPhone, String modelType) throws Exception {
		try {
			String sql = " SELECT COUNT(1) FROM user_phone_yzm WHERE USER_PHONE = ? AND MODEL_TYPE = ? ";
			return baseDao.find(sql, Integer.class, userPhone, modelType) > 0;
		} catch (Exception e) {
			log.error("根据模块类型判断手机验证码是否存在出错了！", e);
		}
		return false;
	}
	
	/**
	 * 
	 * 获取开启状态的短信接口配置
	 * 
	 * @author 姚龙   创建时间：2017-05-16 09:36:43
	 */
	private BaseSmsApiConfig findOpenedSmsApiConfig() {
		BaseSmsApiConfig baseSmsApiConfig = null;

		String sql = " SELECT * FROM base_sms_api_config WHERE USE_FLAG = 1 ORDER BY OPT_TIME DESC LIMIT 1";
		try {
			List<BaseSmsApiConfig> dataList = this.baseDao.findList(sql, RowMapperFactory.newInstance(BaseSmsApiConfig.class));
			if (dataList != null && !dataList.isEmpty()) {
				baseSmsApiConfig = dataList.get(0);
			}
		} catch (Exception e) {
			log.error("获取开启状态的短信接口配置出错", e);
		}
		return baseSmsApiConfig;
	}
}
